#include "Config.h"
#include "HttpBase.h"
#include "wch/StringTokenizer.h"
using namespace wch;

HttpBase::HttpBase( UInt16 port )
: _port(port), _base(nullptr), _server(nullptr), _timer( nullptr )
{
}

bool HttpBase::init()
{
#ifdef _WIN32
	WSADATA wsaData;
	if(WSAStartup(MAKEWORD(2,2) , &wsaData) != 0) 
		return false;
#endif
	_base = event_base_new();
	_server = evhttp_new( _base );
	if ( _server == nullptr )
		return false;
	int ret = evhttp_bind_socket( _server, "0.0.0.0",  _port );
	if ( ret != 0 )
		return false;

	return true;
}

void HttpBase::destroy()
{
	event_base_dispatch( _base );
	evhttp_free( _server );
#ifdef _WIN32
	WSACleanup();
#endif
}

void HttpBase::generic_handler(struct evhttp_request *req, void *arg)
{
	HttpBase * http = static_cast<HttpBase *>(arg);
	std::string content = evhttp_request_get_uri( req );
	if ( !content.empty() )
	{
		if ( content[0] == '/' )
		{
			content.erase( content.begin() );
			http->processReq( content );
		}
	}
}

void HttpBase::generic_timer(evutil_socket_t listener, short event, void *arg)
{
	HttpBase * http = static_cast<HttpBase *>(arg);
	if (!evtimer_pending(http->_timer, nullptr))
	{
		event_del(http->_timer);
		evtimer_add(http->_timer, &http->_tv);
	}
	//
	http->processResp();
}

void HttpBase::processRespImpl(std::vector<std::string>& resps)
{
	//for (size_t i = 0; i < resps.size(); ++i)
	//{
	//	struct evbuffer *buf = evbuffer_new();
	//	if (buf != nullptr)
	//	{
	//		std::string buffer("http://114.55.118.98/resp?");
	//		buffer.append( resps[i] );
	//		struct evhttp_connection * conn = evhttp_connection_base_new(_base, nullptr, buffer.c_str(), 80);
	//		struct
	//		evbuffer_add_printf(buf, "%s", resps[i].c_str());
	//		evhttp_send_reply(req, HTTP_OK, "OK", buf);
	//		evbuffer_free(buf);
	//	}
	//}
}

void HttpBase::run()
{
	if ( !init() )
		return;
	evhttp_set_gencb( _server, generic_handler, this );
	printf("Http server start OK! \n");
	_tv.tv_sec = 1;
	_tv.tv_usec = 0;
	_timer = evtimer_new(_base, generic_timer, this);
	evtimer_add(_timer, &_tv);
	event_base_dispatch( _base );
	destroy();
}